package jnpf.database.util;

import com.alibaba.druid.pool.DruidDataSource;
import jnpf.database.model.dto.DataSourceDTO;
import jnpf.database.model.interfaces.DataSourceMod;
import jnpf.database.source.DbBase;
import jnpf.database.source.impl.DbOracle;
import jnpf.exception.DataException;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

/**
 * Connection数据连接相关工具类
 *
 * @author JNPF开发平台组
 * @version V3.2.0
 * @copyright 引迈信息技术有限公司
 * @date 2021/10/6
 */
public class ConnUtil {

    /**
     * 连接Connection
     */
    public static Connection getConn(DataSourceMod dbSourceOrDbLink) throws DataException {
        return getConn(dbSourceOrDbLink, null);
    }
    /**
     * 指定库名（多租户）
     */
    public static Connection getConn(DataSourceMod dataSourceUtil, String dbName) throws DataException {
        DataSourceDTO dsd = dataSourceUtil.convertDTO(dbName);
        // Oracle特殊连接
        if(DbTypeUtil.checkOracle(dsd)){ return getOracleConn(dsd); }
        return getConn(dsd.getAutoUsername(), dsd.getAutoPassword(), getUrl(dsd));
    }

    /**
     * 基础连接方式
     */
    public static Connection getConn(String userName, String password, String url) throws DataException {
        DbBase db = DbTypeUtil.getDb(url);
        return ConnCommon.createConn(db.getDriver(), userName, password, url);
    }

    /* ==================================================== */

    /**
     * oracle特殊连接方式
     */
    private static Connection getOracleConn(DataSourceDTO dsd) throws DataException {
        DbOracle dbOracle = new DbOracle();
        return dbOracle.getOracleConn(dsd, getUrl(dsd));
    }

    /*==============获取数据连接URL==============*/

    public static String getUrl(DataSourceMod dbSourceOrDbLink) {
        return getUrl(dbSourceOrDbLink, null);
    }

    /**
     * 指定库名（多租户）
     *
     * @param dbSourceOrDbLink 数据源
     * @param dbName           数据库名
     * @return url连接
     */
    public static String getUrl(DataSourceMod dbSourceOrDbLink, String dbName) {
        return DbBase.BaseCommon.getDbBaseConnUrl(dbSourceOrDbLink, dbName);
    }

    /**
     * 获取DruidDataSource
     */
    public static DruidDataSource getDruidDataSource(DataSourceUtil dataSourceUtil) throws DataException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUsername(dataSourceUtil.getUserName());
        druidDataSource.setPassword(dataSourceUtil.getPassword());
        //jdbc-url
        druidDataSource.setUrl(ConnUtil.getUrl(dataSourceUtil));
        //数据库驱动
        druidDataSource.setDriverClassName(DbTypeUtil.getDb(dataSourceUtil).getDriver());
        return druidDataSource;
    }



    /**
     * 以下为ConnUtil上面非显性的公开方法
     * 让调用者只关注getConn方法而不造成干扰
     */
    public static class ConnCommon {

        /**
         * （基础）获取数据连接
         *
         * @param driver   驱动
         * @param userName 用户
         * @param password 密码
         * @param url      url
         * @return 数据库连接
         * @throws DataException ignore
         */
        public static Connection createConn(String driver, String userName, String password, String url) throws DataException {
            try {
                Class.forName(driver);
                return DriverManager.getConnection(url, userName, password);
            } catch (Exception e) {
                e.printStackTrace();
                throw DataException.errorLink(e.getMessage());
            }
        }


        public static Connection createConnByProp(String driver, String userName, String password, String url, Properties conProps) throws DataException {
            try {
                conProps.put("user", userName);
                conProps.put("password", password);
                Class.forName(driver);
                return DriverManager.getConnection(url, conProps);
            } catch (Exception e) {
                throw new DataException(e.getMessage());
            }
        }

        /**
         * 开启数据库获取表注解连接
         *
         * @param dbSourceOrDbLink 数据源对象
         * @return ignore
         */
        public static Connection getConnRemarks(DataSourceUtil dbSourceOrDbLink) throws DataException {
            Properties props = new Properties();
            //设置可以获取remarks信息
            props.setProperty("remarks", "true");
            props.setProperty("remarksReporting", "true");
            //设置可以获取tables remarks信息
            props.setProperty("useInformationSchema", "true");
            return createConnByProp(DbTypeUtil.getDb(getUrl(dbSourceOrDbLink)).getDriver(), dbSourceOrDbLink.getUserName(), dbSourceOrDbLink.getPassword(),
                    getUrl(dbSourceOrDbLink), props);
        }

    }

}


